/*
 ******************************************************************************************************************************************************************************************
*@file                       touch.c
*@author        触摸按键 功能   实现 ：  单击 、双击、 长按  检测
*@data          2022/03/12
*@version                    v1.0
*@par Copyright(c):xavier
*
*@par History:
*     version:author,date,desc
*     v1.0   :create this file
*     v1.1   :修改长按 响应输出时间，长按时间达到，及输出相应的长按状态。
* 	          例如：长按4S， 会依次输出  长按2S、长按4S.
*	  v1.2   :取消IO中断、定时器计时，修改为任务调用 按键扫描，需要注意调用时基问题
*             时基在宏定义中设置   KEY_PARITY_ms   建议值100ms ，最大不大于400ms
*
demo：
初始化
	//【1】按键初始化  GPIO输入模式
	touch_key_init();

	//【2】触摸按键数据初始化
	touch_data_init();

中断或者任务定时调用
	//【3】按键扫描  调用时基为 100ms  若是时基 不是100ms ，需修改  宏定义   KEY_PARITY_ms
	touch_timing_scan();

检测按键
	//【4】获取按键状态  ,清除 按键状态
	key_state =get_touch_key_ststae();


// 按键状态
enum
{
	Key_Idle = 0,	   // 空闲
	Key_Click,		   // 单击
	Key_DblClick,	   // 双击
	Key_Three_Click,   // 三击
	Key_Long_Press_3s, // 长按
	Key_Long_Press_5s, // 长按
	Key_Long_Press_7s, // 长按
};

*******************************************************************************************************************************************************************************************
*/
#include "touch.h"
#include "main.h"

static TOUCH_DATA_T touch_data;

/*
set_touch_key_ststae
设置按键状态
*/
static void set_touch_key_ststae(unsigned char state)
{
#if printf_log // 测试
	switch (state)
	{
	case Key_Idle :
		printf("\r\n Key_Idle  \r\n");
		break;
	case Key_Click:	
		printf("\r\n Key_Click \r\n");
		break;
	case Key_DblClick:
		printf("\r\n Key_DblClick\r\n");
		break;
	case Key_Three_Click:
		printf("\r\n Key_Three_Click \r\n");
		break;
	case Key_Long_Press_3s:
		printf("\r\n Key_Long_Press_3s\r\n");
		break;
	case Key_Long_Press_5s:
		printf("\r\n Key_Long_Press_5s \r\n");
		break;
	default:
		break;
	}
#endif
	touch_data.key_state = state;
}
/*
get_touch_key_ststae
获取按键状态  ,并清除按键状态
*/
unsigned char get_touch_key_ststae(void)
{
	char key_state = touch_data.key_state;
	//		dbg_printf(" key_state=%bd\r\n ",key_state);
	if (key_state != Key_Idle)
	{
#if printf_log // 测试
		switch (key_state)
		{
		case Key_Idle:
			printf("\r\n Key_Idle  \r\n");
			break;
		case Key_Click:
			printf("\r\n Key_Click \r\n");
			break;
		case Key_DblClick:
			printf("\r\n Key_DblClick\r\n");
			break;
		case Key_Three_Click:
			printf("\r\n Key_Three_Click \r\n");
			break;
		case Key_Long_Press_3s:
			printf("\r\n Key_Long_Press_3s\r\n");
			break;
		case Key_Long_Press_5s:
			printf("\r\n Key_Long_Press_5s \r\n");
			break;
		case Key_Long_Press_7s:
			printf("\r\n Key_Long_Press_7s \r\n");
			break;
		default:
			break;
		}
#endif
		set_touch_key_ststae(Key_Idle);
	}
	return key_state;
}
/*
set_touch_key_actual_state
设置按键实际状态  用于部分指令需要按键松开在响应
*/
static void set_touch_key_actual_state(unsigned char state)
{
	touch_data.key_actual_state = state;
}
/*
get_touch_key_actual_state
获取按键实际状态  用于部分指令需要按键松开在响应
*/
static unsigned char get_touch_key_actual_state(void)
{
	#if printf_log // 测试
	printf( "key state =%bu ",touch_data.key_actual_state);
	#endif
	return touch_data.key_actual_state;
}
/*
set_touch_key_last_state
设置按键上一次的状态
*/
static void set_touch_key_last_state(unsigned char state)
{
	touch_data.key_last_state = state;
}
/*
get_touch_key_last_state
获取按键实际状态  用于部分指令需要按键松开在响应
*/
static unsigned char get_touch_key_last_state(void)
{
	return touch_data.key_last_state;
}
/*
set_touch_key_last_time
设置按键最后一次触摸的时间
*/
static void set_touch_key_last_time(unsigned int time)
{
	touch_data.key_last_time = time;
}
/*
get_touch_key_last_time
获取按键最后一次触摸的时间
*/
static unsigned int get_touch_key_last_time(void)
{
	return touch_data.key_last_time;
}
/*
add_touch_key_last_time
按键最后一次触摸的时间   累计
*/
static void add_touch_key_last_time(void)
{
	if (touch_data.key_last_time < 65535)
		touch_data.key_last_time++;
}

/*
set_touch_key_press_time
设置按键按下的时间
*/
static void set_touch_key_press_time(unsigned char time)
{
	touch_data.key_press_time = time;
}
/*
add_touch_key_press_time
 按键按下的时间   累计
*/
static void add_touch_key_press_time(void)
{
	// 连续两次按下 才计算
	if (get_touch_key_actual_state() == Key_Press && get_touch_key_last_state() == Key_Press && touch_data.key_press_time < 255)
	{
		touch_data.key_press_time++;
	}
}
/*
get_touch_key_press_time
获取按键按下的时间
*/
static unsigned char get_touch_key_press_time(void)
{
	return touch_data.key_press_time;
}
/*
add_touch_key_press_count
按键按下次数   累计
*/
static void add_touch_key_press_count(void)
{
	if (touch_data.key_press_count < 255)
		touch_data.key_press_count++;
}
/*
add_touch_key_press_count
按键按下次数   累计
*/
static void set_touch_key_press_count(unsigned char count)
{
	touch_data.key_press_count = count;
}
/*
get_touch_key_press_time
获取按键按下的时间
*/
static unsigned char get_touch_key_press_count(void)
{
	return touch_data.key_press_count;
}
/*
key_last_time_up
上一次触摸时间  更新
*/
static void key_last_time_up(void)
{
	if (get_touch_key_actual_state() == Key_Undo && get_touch_key_last_state() == Key_Undo)
	{
		// 松开后累计
		add_touch_key_last_time();
	}
	else
	{ // 刚松开时 或者 按下 清零
		set_touch_key_last_time(0);
	}
}
/*
touch_key_press_coun_up
按键按压 计数
*/
static void touch_key_press_coun_up(void)
{
	if (get_touch_key_actual_state() == Key_Press)
	{
		if (get_touch_key_last_state() == Key_Undo && get_touch_key_last_time() <= Key_DblClick_Time) // 刚按下时 计数
		{
			// 按键按下次数   累计
			add_touch_key_press_count();
		}
	}
	// 长按时，松开，不计算在短按次数中
	if (get_touch_key_press_time() > Key_Long_Press_Time_3s)
	{
		set_touch_key_press_count(0); // 连击计数清空
	}
}
/*
触摸按键状态扫描
*/
void touch_key_state_scan(void)
{
	if (GPIO_Read_Key_Status() == Touch_Key_Effectivity_State)
	{										   // 按下
		set_touch_key_actual_state(Key_Press); // 按键实际状态
		#if printf_log // 测试
		if (get_touch_key_last_state() != get_touch_key_actual_state())
		{
			printf("按下");
		}
		#endif
	}
	else
	{										  // 松开
		set_touch_key_actual_state(Key_Undo); // 按键实际状态
		#if printf_log // 测试
		if (get_touch_key_last_state() != get_touch_key_actual_state())
		{
			printf("松开");
		}
		#endif
		// 重置按键按键时间 计时  长按松开时，会多出现一次 按键信号 特增加 按键按键时间 清零
		set_touch_key_press_time(0);
		touch_data.key_long_press_3s_state = 0;
		touch_data.key_long_press_5s_state = 0;
		touch_data.key_long_press_7s_state = 0;
	}
}
/*
按键长按扫描
*/
static void key_long_press_scan(void)
{
	if (get_touch_key_press_time() >= Key_Long_Press_Time_7s && touch_data.key_long_press_7s_state == 0)
	{											 // 判断按下时间
		set_touch_key_ststae(Key_Long_Press_7s); // 长按
		#if printf_log // 测试
		printf("7s");
		#endif
		set_touch_key_press_count(0); // 连击计数清空
		touch_data.key_long_press_7s_state = 1;
	}
	else if (get_touch_key_press_time() >= Key_Long_Press_Time_5s && touch_data.key_long_press_5s_state == 0)
	{											 // 判断按下时间
		set_touch_key_ststae(Key_Long_Press_5s); // 长按
		#if printf_log // 测试
		printf("5s");
		#endif
		set_touch_key_press_count(0); // 连击计数清空
		touch_data.key_long_press_5s_state = 1;
	}
	else if (get_touch_key_press_time() >= Key_Long_Press_Time_3s && touch_data.key_long_press_3s_state == 0)
	{											 // 判断按下时间
		set_touch_key_ststae(Key_Long_Press_3s); // 长按
		#if printf_log // 测试
		printf("3s");
		#endif
		set_touch_key_press_count(0); // 连击计数清空
		touch_data.key_long_press_3s_state = 1;
	}
}
/*
按键按压扫描
*/
static void key_press_scan(void)
{
	// 松开情况下，短按按键有效
	if (get_touch_key_actual_state() == Key_Undo && get_touch_key_last_time() > Key_DblClick_Time)
	{
		if (get_touch_key_press_count() >= 1)
		{
			if (get_touch_key_press_count() == 1)
			{
				set_touch_key_ststae(Key_Click); // 单击
				#if printf_log // 测试
				printf(" Click ");
				#endif
				/***************** 产品需求，大于两次的连击，也按照 双击处理 *******************/
				//}else if(get_touch_key_press_count()==2)
			}
			else if (get_touch_key_press_count() == 2)
			{
				set_touch_key_ststae(Key_DblClick); // 双击
				#if printf_log // 测试
				printf(" DblClick ");
				#endif
			}
			else if (get_touch_key_press_count() == 3)
			{
				set_touch_key_ststae(Key_Three_Click); // 三击
				#if printf_log // 测试
				printf(" Three Click ");
				#endif
			}
			else
			{
				// printf(" invalid \r\n");
				// 其余 连击无效
			}
			set_touch_key_press_count(0); // 连击计数清空
		}
	}
}
/*
触摸按键 定时 扫描
*/
void touch_timing_scan(void)
{

	set_touch_key_last_state(get_touch_key_actual_state());
	touch_key_state_scan();
	key_last_time_up(); // 上一次触摸时间  更新

	// 按键按下的时间   累计
	add_touch_key_press_time();
	// 按键最后一次触摸的时间   累计
	add_touch_key_last_time();
	// 按键按压 计数
	touch_key_press_coun_up();
	// 按键长按扫描
	key_long_press_scan();
	// 按键按压扫描
	key_press_scan();
	// printf("press_time=%u  \r\n", touch_data.key_press_time);  // 按下的时间
	// printf("press_count=%u \r\n", touch_data.key_press_count); // 按下的次数
	// printf("last_time=%u   \r\n", touch_data.key_last_time);   // 最后一次触摸的时间
	// printf("state=%u       \r\n", touch_data.key_state);	   // 按下的时间
}

/*
touch_data_init()
触摸按键数据初始化
*/
void touch_data_init(void)
{
	set_touch_key_ststae(Key_Idle);
	set_touch_key_last_time(0);
	set_touch_key_actual_state(Key_Undo); // 按键实际状态  松开
}

/*
触摸按键初始化   GPIO输入模式
*/
void touch_key_init(void)
{
	// 按键状态初始化
	TYPE_LL_GPIO_INIT gpio_struct;
	memset(&gpio_struct, 0x00, sizeof(gpio_struct));
	gpio_struct.gpio_pin = KEY_GPIO_PIN;
	gpio_struct.gpio_mode = LL_GPIO_MODE_IN; // 输入模式
	gpio_struct.gpio_pupd = LL_GPIO_PUPD_UP;
	ll_gpio_init(KEY_GPIOx, &gpio_struct);
}
